package com.ruoyi.health.report.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.ruoyi.common.core.constant.ZkxcRedisConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.PrimaryKeyIdUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.AiResult;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.customer.api.domain.ZkxcUser;
import com.ruoyi.health.api.enums.ReportEnum;
import com.ruoyi.health.report.action.processor.SaveImageActionProcessor;
import com.ruoyi.health.report.api.IRemoteFileService;
import com.ruoyi.health.report.api.IRemoteSysConfigService;
import com.ruoyi.health.report.domain.HealthAnalysisVO;
import com.ruoyi.health.report.domain.HealthReport;
import com.ruoyi.health.report.domain.zkxc.*;
import com.ruoyi.health.report.mapper.HealthReportMapper;
import com.ruoyi.health.report.mapper.ZkxcPushDataMapper;
import com.ruoyi.health.report.service.IHealthZkxcService;
import com.ruoyi.health.report.service.PushRegistrationService;
import com.ruoyi.health.report.utils.AesUtil;
import com.ruoyi.system.api.domain.SysFile;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @author ChenYF
 * @date 2025-09-03 15:25
 */
@Service
public class HealthZkxcServiceImpl implements IHealthZkxcService {
    @Autowired
    private IRemoteFileService fileService;
    @Autowired
    private IRemoteSysConfigService sysService;
    @Autowired
    private ZkxcPushDataMapper zkxcPushDataMapper;
    @Autowired
    private HealthReportMapper reportMapper;
    @Autowired
    private SaveImageActionProcessor saveImageActionProcessor;
    @Autowired
    private RedisService redisService;

    @Autowired
    private PushRegistrationService pushRegistrationService;

    private Gson gson =  new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();

    private String fileNameFormat = "%s_%s_%s";


    @Override
    public AiResult saveZkxcPushData(ZkxcPushBaseEntity pushData) {
        // 基础信息
        CollectInfoEntity info = pushData.getCollectInfoEntity();
        // 舌诊信息
        SzPushEntity szPushEntity = pushData.getSzPushEntity();
        // 脉诊
        MzPushEntity mzPushEntity = pushData.getMzPushEntity();
        // 问诊信息
        WzPushEntity wzPushEntity = pushData.getWzPushEntity();
        // 面诊信息
        FacePushEntity facePushEntity = pushData.getFacePushEntity();

        // 1、根据基础信息查询用户信息
        //
        return AiResult.success();
    }

    /**
     * 插入数据
     * @param jsonObject      原始数据
     * @param pdfFile    文件内容
     * @return
     */
    @Override
    public AiResult insertZkxcPushData(JSONObject jsonObject, List<MultipartFile> pdfFile) {

        String channel = jsonObject.getString(ZkxcRedisConstants.Channel);
        String reqData = jsonObject.getString(ZkxcRedisConstants.ReqData);

        // 数据转为实体
        ZkxcPushBaseEntity baseEntity = decrypt(reqData);
        ZkxcPushDataEntity dataEntity = gson.fromJson(gson.toJson(jsonObject), ZkxcPushDataEntity.class);

        // 基础信息
        CollectInfoEntity info = baseEntity.getCollectInfoEntity();
        Long id = info.getId();
        Long patientId = info.getPatientId(); // 三方id -- 体检表id
        String createTime = info.getCreateTime();

        // 检测数据是否已生成过
        AjaxResult ajaxResult = sysService.selectZkxcUserById(patientId);
        Object obj = ajaxResult.get("data");
        ZkxcUser zkxcUser;
        if (ObjectUtils.isNotEmpty(obj)) {
            zkxcUser = gson.fromJson(gson.toJson(obj), ZkxcUser.class);
//            if (zkxcUser.getStatus() == 1) {
//                return AiResult.fail("数据已存在");
//            }
        } else {
            return AiResult.fail();
        }

        // 上传文件
        List<String> urls = new ArrayList<>();
        pdfFile.forEach(file -> {
            String fileName = String.format(fileNameFormat, patientId, id, DateUtils.dateTimeNow());

            R<SysFile> upload = fileService.upload(file, fileName);
            if (R.isSuccess(upload)) {
                SysFile data = upload.getData();
                urls.add(data.getUrl());
            }
        });

        // 保存数据
        // 1、添加健康日志 -- 绑定用户
        Date date = StringUtils.isEmpty(createTime) ? DateUtils.getNowDate() : DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, createTime);

        HealthReport healthReport = new HealthReport();
        healthReport.setId(PrimaryKeyIdUtils.getSysIdWorker().nextId());
        healthReport.setTsStart(date);
        healthReport.setCreateTime(DateUtils.getNowDate());
        healthReport.setCustomerId(zkxcUser.getCustomerId());
        healthReport.setCustomerName(info.getRealName());
        healthReport.setType(ReportEnum.SIZHEN.getCode());
        int i = reportMapper.insertHealthReport(healthReport);
        if (i <= 0) {
            return AiResult.fail("添加健康日志失败");
        }

        // 2、修改绑定数据
        zkxcUser.setId(patientId);  
        zkxcUser.setChannel(StringUtils.isEmpty(channel) ? null : Integer.parseInt(channel));
        zkxcUser.setMac(info.getMac());
        zkxcUser.setStatus(1);
        zkxcUser.setReportId(healthReport.getId());
        sysService.updateZkxcUser(zkxcUser);

        // 3.将原始数据域解包数据缓存到redis
        Map<String, Object> map = new HashMap<>();
        map.put(ZkxcRedisConstants.ReqData, reqData);
        map.put(ZkxcRedisConstants.BaseEntity, gson.toJson(baseEntity));
        redisService.setCacheMap(ZkxcRedisConstants.ResDataKey + id, map);
        // 原始数据不存到数据库
        dataEntity.setReqData(null);

        // 4、保存原始数据
        dataEntity.setId(id);
        dataEntity.setCustomerId(zkxcUser.getCustomerId());
        dataEntity.setPdfFileUrl(gson.toJson(urls));
        dataEntity.setHealthReportId(healthReport.getId());
        int insert = zkxcPushDataMapper.insertZkxcPushDataEntity(dataEntity);
        if (insert > 0) {
            pushRegistrationService.pushRegistration(zkxcUser);
        }
        return insert > 0 ? AiResult.success() : AiResult.fail();
    }

    @Override
    public AjaxResult getZkxcReport(Long healthReportId) {
        return AjaxResult.success(getZkxcReportByReportId(healthReportId));
    }

    @Override
    public HealthAnalysisVO getZkxcReportByReportId(Long healthReportId) {
        List<ZkxcPushDataEntity> list = zkxcPushDataMapper.selectZkxcPushDataByParam(new ZkxcPushDataEntity().setHealthReportId(healthReportId));
        if (ObjectUtils.isEmpty(list)) {
            return null;
        }
        // 由于表中存储的healthReportId设置了唯一索引，所以此处只会查出一条数据
        ZkxcPushDataEntity entity = list.get(0);
        HealthAnalysisVO vo = new HealthAnalysisVO();
        BeanUtils.copyProperties(entity, vo);
        // 由于原始数据缓存到了redis中，所以此处直接从redis中获取数据
        String baseEntityStr = redisService.getCacheMapValue(ZkxcRedisConstants.ResDataKey + entity.getId(), ZkxcRedisConstants.BaseEntity);
        ZkxcPushBaseEntity baseEntity = gson.fromJson(baseEntityStr, ZkxcPushBaseEntity.class);
        if (ObjectUtils.isEmpty(baseEntity)) {
            // 如果数据缓存中不存在数据，则重新解码数据
            baseEntity = decrypt(entity.getReqData());
        }
        vo.setBaseEntity(baseEntity);
        vo.setPdfFileUrlList(entity.getPdfFileUrl());
        return vo;
    }

    @Override
    public String getReportUrlByReportId(Long id) {
        String url = zkxcPushDataMapper.getReportUrlByReportId(id);
        List<String> strings = JSONArray.parseArray(url, String.class);
        return strings.get(0);
    }


    /**
     * 加密内容解码
     *
     * @param aesStr
     * @return
     */
    private ZkxcPushBaseEntity decrypt(String aesStr) {
        String aesKey = sysService.getConfigKey("zkxc.aesKey").getMsg();
        final SecretKey secretKey = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), "AES");
        String re = AesUtil.decrypt(aesStr, secretKey);
        ZkxcPushBaseEntity pushEntity = gson.fromJson(re, ZkxcPushBaseEntity.class);
        // 在获取到实体值之后调用
        CollectInfoEntity info = pushEntity.getCollectInfoEntity();
        saveImageActionProcessor.processSaveImageAction(pushEntity, info.getPatientId(),  info.getId());

        return pushEntity;
    }

    public static void main(String[] args) {
        String aesKey = "zk20230101000000";
        String aesStr = "zk20230101000000";
        final SecretKey secretKey = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), "AES");
        String re = AesUtil.decrypt(aesStr, secretKey);
    }
}
